﻿using Compass.DataService.Domain;
using Compass.DataService.Infrastructure;
using Compass.LogisticService.Infrastructure;
using Compass.PlanService.Domain;
using Compass.PlanService.Infrastructure;
using Compass.QualityService.Domain;
using Compass.QualityService.Infrastructure;
using Compass.TodoService.Domain;
using Compass.TodoService.Infrastructure;
using Compass.Wasm.Server.Services.Identities;
using Compass.Wasm.Server.Services.Categories;
using Compass.Wasm.Server.Services.Data;
using Compass.Wasm.Server.Services.Data.Cabins;
using Compass.Wasm.Server.Services.Data.Ceilings;
using Compass.Wasm.Server.Services.Data.Hoods;
using Compass.Wasm.Server.Services.Data.UL;
using Compass.Wasm.Server.Services.Plans;
using Compass.Wasm.Server.Services.Projects;
using Compass.Wasm.Server.Services.Todos;
using Compass.LogisticService.Domain;
using Compass.PurchaseService.Domain;
using Compass.PurchaseService.Infrastructure;
using Compass.Wasm.Server.Services.Logistics;
using Compass.Wasm.Server.Services.Purchases;
using Compass.Wasm.Server.Services.Wms;
using Compass.WmsService.Domain;
using Compass.WmsService.Infrastructure;

namespace Compass.Wasm.Server;

public static class Register
{
    public static WebApplicationBuilder RegisterAppServices(this WebApplicationBuilder builder)
    {

        #region 【中心配置数据库】的连接字符串
        builder.Host.ConfigureAppConfiguration((hostCtx, configBuilder) =>
        {
            //从环境变量中获取连接字符串
            string connStr = builder.Configuration.GetValue<string>("DefaultDB:ConnStr");
            //NuGet安装：Install-Package Zack.AnyDBConfigProvider
            configBuilder.AddDbConfiguration(() => new SqlConnection(connStr), reloadOnChange: true, reloadInterval: TimeSpan.FromSeconds(5));
        });
        #endregion

        #region 工作单元
        builder.Services.AddMediatR(Assembly.GetExecutingAssembly());//传递当前运行的程序集
        builder.Services.Configure<MvcOptions>(options =>
        {
            options.Filters.Add<UnitOfWorkFilter>();
        });
        #endregion

        #region FluentValidation请求数据校验
        //NuGet安装：Install-Package FluentValidation.AspNetCore
        //配置FluentValidation
        builder.Services.AddFluentValidationAutoValidation()
            .AddValidatorsFromAssembly(Assembly.GetEntryAssembly());
        #endregion

        #region 配置Serilog日志
        //NuGet安装：Install-Package Serilog.AspNetCore
        //配置Serilog日志
        builder.Services.AddLogging(loggingBuilder =>
        {
            Log.Logger = new LoggerConfiguration()
                .MinimumLevel.Warning()
                .Enrich.FromLogContext()
                //.WriteTo.Console()
                .WriteTo.File($"d:/compass.log/compass.wasm.log") //记录日志到文件
                .CreateLogger();
            loggingBuilder.AddSerilog();
        });
        #endregion

        #region Authentication,Authorization
        //NuGet安装：Install-Package Zack.JWT
        //开始:Authentication,Authorization
        //只要需要校验Authentication报文头的地方（非IdentityService.WebAPI项目）也需要启用这些
        //IdentityService项目还需要启用AddIdentityCore
        builder.Services.AddAuthorization();
        builder.Services.AddAuthentication();
        JWTOptions jwtOpt = builder.Configuration.GetSection("JWT").Get<JWTOptions>();
        builder.Services.AddJWTAuthentication(jwtOpt);
        //启用Swagger中的【Authorize】按钮。这样就不用每个项目的AddSwaggerGen中单独配置了
        builder.Services.Configure<SwaggerGenOptions>(c =>
        {
            c.AddAuthenticationHeader();
        });
        //配置JWT的选项，包含secKey和过期时间
        builder.Services.Configure<JWTOptions>(builder.Configuration.GetSection("JWT"));
        #endregion

        #region RabbitMQ
        //NuGet,安装Install-Package Zack.EventBus
        //配置RabbitMQ，从中心化服务器读取RabbitMQ的服务器地址和交换机名
        builder.Services.Configure<IntegrationEventRabbitMQOptions>(builder.Configuration.GetSection("RabbitMQ"));
        //配置消息队列名
        builder.Services.AddEventBus("Compass.Wasm", Assembly.GetExecutingAssembly());
        #endregion

        #region Redis
        //Redis未开启？wsl
        //sudo service redis-server start
        //密码123
        //redis-cli
        //ping
        //keys *
        //访问http://127.0.0.1:15672/#/
        //配置Redis的服务器，分布式缓存
        string redisConnStr = builder.Configuration.GetValue<string>("Redis:ConnStr");
        IConnectionMultiplexer redisConnMultiplexer = ConnectionMultiplexer.Connect(redisConnStr);
        builder.Services.AddSingleton(typeof(IConnectionMultiplexer), redisConnMultiplexer);

        #endregion

        #region AutoMapper
        //Install-Package AutoMapper
        //Install-Package AutoMapper.Extensions.Microsoft.DependencyInjection
        //https://dev.to/moe23/add-automapper-to-net-6-3fdn
        builder.Services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies());
        #endregion


        return builder;
    }
    public static WebApplicationBuilder RegisterFileServices(this WebApplicationBuilder builder)
    {
        #region FileService
        //数据库，DbContext
        builder.Services.AddDbContext<FileDbContext>(options =>
        {
            //指定连接的数据库
            var connStr = builder.Configuration.GetSection("DefaultDB:ConnStr").Value;
            options.UseSqlServer(connStr);
        });
        //文件服务(本地存储)
        builder.Services.Configure<SMBStorageOptions>(builder.Configuration.GetSection("FileService:SMB"));
        //HttpContextAccessor 默认实现了它简化了访问HttpContext。用来访问HttpContext
        builder.Services.AddHttpContextAccessor();
        builder.Services.AddScoped<IStorageClient, SMBStorageClient>();//本机磁盘当备份服务器
        builder.Services.AddScoped<IStorageClient, MockCloudStorageClient>();//文件保存在wwwroot文件夹下
        builder.Services.AddScoped<FileDomainService>();
        builder.Services.AddScoped<IFileRepository, FileRepository>();

        #endregion

        return builder;
    }

    public static WebApplicationBuilder RegisterIdentityServices(this WebApplicationBuilder builder)
    {
        #region IdentityService
        //数据库，DbContext
        builder.Services.AddDbContext<IdentityDbContext>(options =>
        {
            //指定连接的数据库
            var connStr = builder.Configuration.GetSection("DefaultDB:ConnStr").Value;
            options.UseSqlServer(connStr);
        });
        builder.Services.AddScoped<IdentityDomainService>();
        builder.Services.AddScoped<IIdentityRepository, IdentityRepository>();
        builder.Services.AddDataProtection();
        //登录、注册的项目除了要启用WebApplicationBuilderExtensions中的初始化之外，还要如下的初始化
        //不要用AddIdentity，而是用AddIdentityCore
        //因为用AddIdentity会导致JWT机制不起作用，AddJwtBearer中回调不会被执行，因此总是Authentication校验失败
        //https://github.com/aspnet/Identity/issues/1376
        IdentityBuilder idBuilder = builder.Services.AddIdentityCore<User>(options =>
        {
            options.Password.RequireDigit = false;
            options.Password.RequireLowercase = false;
            options.Password.RequireUppercase = false;
            options.Password.RequireNonAlphanumeric = false;
            options.Password.RequiredLength = 2;
            options.Password.RequireLowercase = false;
            //不能设定RequireUniqueEmail，否则不允许邮箱为空
            //options.User.RequireUniqueEmail = true;
            //以下两行，把GenerateEmailConfirmationTokenAsync验证码缩短
            options.Tokens.PasswordResetTokenProvider = TokenOptions.DefaultEmailProvider;
            options.Tokens.EmailConfirmationTokenProvider = TokenOptions.DefaultEmailProvider;
        });
        idBuilder = new IdentityBuilder(idBuilder.UserType, typeof(Role), builder.Services);
        idBuilder.AddEntityFrameworkStores<IdentityDbContext>().AddDefaultTokenProviders()
            .AddRoleManager<RoleManager<Role>>()
            .AddUserManager<IdentityUserManager>();
        //发送邮件
        builder.Services.AddScoped<IEmailSender, EmailSender>();
        //获取中心服务器中的smtp设置
        builder.Services.Configure<SmtpOptions>(builder.Configuration.GetSection("Smtp"));

        builder.Services.AddScoped<IUserService, UserService>();

        #endregion

        return builder;
    }

    public static WebApplicationBuilder RegisterCategoryServices(this WebApplicationBuilder builder)
    {
        #region CategoryService
        //数据库，DbContext
        builder.Services.AddDbContext<CategoryDbContext>(options =>
        {
            //指定连接的数据库
            var connStr = builder.Configuration.GetSection("DefaultDB:ConnStr").Value;
            options.UseSqlServer(connStr);
        });
        builder.Services.AddScoped<CategoryDomainService>();
        builder.Services.AddScoped<ICategoryRepository, CategoryRepository>();

        builder.Services.AddScoped<IProductService, ProductService>();
        builder.Services.AddScoped<IModelService, ModelService>();
        builder.Services.AddScoped<IModelTypeService, ModelTypeService>();
        builder.Services.AddScoped<IMaterialItemService, MaterialItemService>();//物料
        builder.Services.AddScoped<IAccCutListService, AccCutListService>();
        builder.Services.AddScoped<IDrawingNumberService, DrawingNumberService>();

        #endregion

        return builder;
    }

    public static WebApplicationBuilder RegisterProjectServices(this WebApplicationBuilder builder)
    {
        #region ProjectService
        //数据库，DbContext
        builder.Services.AddDbContext<ProjectDbContext>(options =>
        {
            //指定连接的数据库
            var connStr = builder.Configuration.GetSection("DefaultDB:ConnStr").Value;
            options.UseSqlServer(connStr);
        });
        builder.Services.AddScoped<ProjectDomainService>();
        builder.Services.AddScoped<IProjectRepository, ProjectRepository>();

        builder.Services.AddScoped<IProjectService, Services.Projects.ProjectService>();
        builder.Services.AddScoped<IDrawingService, DrawingService>();
        builder.Services.AddScoped<IModuleService, ModuleService>();
        builder.Services.AddScoped<ICutListService, CutListService>();


        builder.Services.AddScoped<ILessonService, LessonService>();

        #endregion

        return builder;
    }

    public static WebApplicationBuilder RegisterPlanServices(this WebApplicationBuilder builder)
    {
        #region PlanService
        //数据库，DbContext
        builder.Services.AddDbContext<PlanDbContext>(options =>
        {
            //指定连接的数据库
            var connStr = builder.Configuration.GetSection("DefaultDB:ConnStr").Value;
            options.UseSqlServer(connStr);
        });
        builder.Services.AddScoped<PlanDomainService>();
        builder.Services.AddScoped<IPlanRepository, PlanRepository>();

        builder.Services.AddScoped<IMainPlanService, MainPlanService>();
        builder.Services.AddScoped<IIssueService, IssueService>();
        builder.Services.AddScoped<IPackingListService, PackingListService>();
        builder.Services.AddScoped<IPackingItemService, PackingItemService>();
        builder.Services.AddScoped<IPalletService, PalletService>();
        builder.Services.AddScoped<IFinishedGoodsCountService, FinishedGoodsCountService>();
        #endregion

        return builder;
    }

    public static WebApplicationBuilder RegisterDataServices(this WebApplicationBuilder builder)
    {
        #region DataService
        //数据库，DbContext
        builder.Services.AddDbContext<DataDbContext>(options =>
        {
            //指定连接的数据库
            var connStr = builder.Configuration.GetSection("DefaultDB:ConnStr").Value;
            options.UseSqlServer(connStr);
        });
        builder.Services.AddScoped<DataDomainService>();
        builder.Services.AddScoped<IDataRepository, DataRepository>();

        builder.Services.AddScoped<IModuleDataService, ModuleDataService>();
        #endregion

        #region CabinService其他组件数据服务
        builder.Services.AddScoped<IAbdDataService, AbdDataService>();

        #endregion
        
        #region HoodService普通烟罩数据服务
        builder.Services.AddScoped<IKviDataService, KviDataService>();
        builder.Services.AddScoped<IKvfDataService, KvfDataService>();
        builder.Services.AddScoped<IUviDataService, UviDataService>();
        builder.Services.AddScoped<IUvfDataService, UvfDataService>();

        builder.Services.AddScoped<IKwiDataService, KwiDataService>();
        builder.Services.AddScoped<IKwfDataService, KwfDataService>();
        builder.Services.AddScoped<IUwiDataService, UwiDataService>();
        builder.Services.AddScoped<IUwfDataService, UwfDataService>();

        builder.Services.AddScoped<IUvimDataService, UvimDataService>();
        builder.Services.AddScoped<IUvirDataService, UvirDataService>();

        builder.Services.AddScoped<IKvvDataService, KvvDataService>();
        builder.Services.AddScoped<ICmodiDataService, CmodiDataService>();
        builder.Services.AddScoped<ICmodfDataService, CmodfDataService>();
        builder.Services.AddScoped<ICmodmDataService, CmodmDataService>();

        builder.Services.AddScoped<IKchDataService, KchDataService>();
        builder.Services.AddScoped<IKmcDataService, KmcDataService>();
        builder.Services.AddScoped<ICxwDataService, CxwDataService>();

        #endregion

        #region ULService UL烟罩数据服务
        builder.Services.AddScoped<IChDataService, ChDataService>();
        builder.Services.AddScoped<ICmDataService, CmDataService>();
        builder.Services.AddScoped<ICmmDataService, CmmDataService>();
        builder.Services.AddScoped<IKvcDataService, KvcDataService>();
        builder.Services.AddScoped<IKvcUvDataService, KvcUvDataService>();
        builder.Services.AddScoped<IKvcUvWwDataService, KvcUvWwDataService>();
        builder.Services.AddScoped<IKvcWwDataService, KvcWwDataService>();
        builder.Services.AddScoped<IKveDataService, KveDataService>();
        builder.Services.AddScoped<IKveUvDataService, KveUvDataService>();
        builder.Services.AddScoped<IKveUvWwDataService, KveUvWwDataService>();
        builder.Services.AddScoped<IKveWwDataService, KveWwDataService>();
        builder.Services.AddScoped<IKvrDataService, KvrDataService>();
        builder.Services.AddScoped<IKvwDataService, KvwDataService>();


        #endregion

        #region CeilingService天花烟罩数据服务
        builder.Services.AddScoped<IKcjDataService, KcjDataService>();
        builder.Services.AddScoped<IUcjDataService, UcjDataService>();
        builder.Services.AddScoped<IKcwDataService, KcwDataService>();
        builder.Services.AddScoped<IUcwDataService, UcwDataService>();

        builder.Services.AddScoped<ICjDataService, CjDataService>();
        builder.Services.AddScoped<IDpDataService, DpDataService>();
        builder.Services.AddScoped<ILfuDataService, LfuDataService>();
        builder.Services.AddScoped<IAnDataService, AnDataService>();
        builder.Services.AddScoped<ISspDataService, SspDataService>();
        builder.Services.AddScoped<ILkDataService, LkDataService>();
        builder.Services.AddScoped<ILpDataService, LpDataService>();
        builder.Services.AddScoped<IInfDataService, InfDataService>();
        builder.Services.AddScoped<IDxfDataService, DxfDataService>();


        #endregion



        return builder;
    }

    public static WebApplicationBuilder RegisterLogisticServices(this WebApplicationBuilder builder)
    {
        #region LogisticDbContext
        //数据库，DbContext
        builder.Services.AddDbContext<LogisticDbContext>(options =>
        {
            //指定连接的数据库
            var connStr = builder.Configuration.GetSection("DefaultDB:ConnStr").Value;
            options.UseSqlServer(connStr);
        });
        builder.Services.AddScoped<LogisticDomainService>();
        builder.Services.AddScoped<ILogisticRepository, LogisticRepository>();

        builder.Services.AddScoped<IImportExportInfoService, ImportExportInfoService>();
        

        #endregion

        return builder;
    }


    public static WebApplicationBuilder RegisterPurchaseServices(this WebApplicationBuilder builder)
    {
        //数据库，DbContext
        builder.Services.AddDbContext<PurchaseDbContext>(options =>
        {
            //指定连接的数据库
            var connStr = builder.Configuration.GetSection("DefaultDB:ConnStr").Value;
            options.UseSqlServer(connStr);
        });

        builder.Services.AddScoped<PurchaseDomainService>();
        builder.Services.AddScoped<IPurchaseRepository, PurchaseRepository>();

        builder.Services.AddScoped<INavItemService, NavItemService>();
        builder.Services.AddScoped<INavInvValuationService, NavInvValuationService>();
        builder.Services.AddScoped<INavInvReportClassService, NavInvReportClassService>();
        builder.Services.AddScoped<INavInvReportGroupService, NavInvReportGroupService>();


        return builder;
    }

    public static WebApplicationBuilder RegisterWmsServices(this WebApplicationBuilder builder)
    {
        #region WmsDbContext
        //数据库，DbContext
        builder.Services.AddDbContext<WmsDbContext>(options =>
        {
            //指定连接的数据库
            var connStr = builder.Configuration.GetSection("DefaultDB:ConnStr").Value;
            options.UseSqlServer(connStr);
        });
        builder.Services.AddScoped<WmsDomainService>();
        builder.Services.AddScoped<IWmsRepository, WmsRepository>();

        builder.Services.AddScoped<IVendorService, VendorService>();
        builder.Services.AddScoped<ICargoService, CargoService>();
        builder.Services.AddScoped<ILocationService,LocationService>();

        builder.Services.AddScoped<IInventoryService, InventoryService>();
        builder.Services.AddScoped<IStockInService, StockInService>();
        builder.Services.AddScoped<IStockOutService, StockOutService>();


        #endregion
        return builder;
    }

    public static WebApplicationBuilder RegisterQualityServices(this WebApplicationBuilder builder)
    {
        #region QualityService
        //数据库，DbContext
        builder.Services.AddDbContext<QualityDbContext>(options =>
        {
            //指定连接的数据库
            var connStr = builder.Configuration.GetSection("DefaultDB:ConnStr").Value;
            options.UseSqlServer(connStr);
        });
        builder.Services.AddScoped<QualityDomainService>();
        builder.Services.AddScoped<IQualityRepository, QualityRepository>();
        #endregion

        return builder;
    }
    

    public static WebApplicationBuilder RegisterXXServices(this WebApplicationBuilder builder)
    {


        return builder;
    }

    public static WebApplicationBuilder RegisterTodoServices(this WebApplicationBuilder builder)
    {
        #region TodoService
        //数据库，DbContext
        builder.Services.AddDbContext<TodoDbContext>(options =>
        {
            //指定连接的数据库
            var connStr = builder.Configuration.GetSection("DefaultDB:ConnStr").Value;
            options.UseSqlServer(connStr);
        });
        builder.Services.AddScoped<TodoDomainService>();
        builder.Services.AddScoped<ITodoRepository, TodoRepository>();
        builder.Services.AddScoped<ITodoService, Services.Todos.TodoService>();
        builder.Services.AddScoped<IMemoService, MemoService>();
        #endregion

        return builder;
    }
}